﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TasksLibrary.Tasks
{
    public class Task: ATask
    {
        static Random RandomIdGenerator = null;

        Dictionary<Type, TaskMessage> mMessages = new Dictionary<Type, TaskMessage>();

        #region Init
        public Task()
        {
            if (RandomIdGenerator == null) RandomIdGenerator = new Random();
            Id = RandomIdGenerator.Next(Int32.MaxValue);
            DateCreated = DateTime.Now;

            Init("ID" + Id.ToString(), 0);
        }

        public Task(int IdParentTask)
        {
            if (RandomIdGenerator == null) RandomIdGenerator = new Random();
            Id = RandomIdGenerator.Next(Int32.MaxValue);
            DateCreated = DateTime.Now;

            Init("ID" + Id.ToString(), IdParentTask);
        }

        public Task(string Name)
        {
            if (RandomIdGenerator == null) RandomIdGenerator = new Random();
            Id = RandomIdGenerator.Next(Int32.MaxValue);
            DateCreated = DateTime.Now;

            Init(Name, 0);
        }

        public Task(string Name, int IdParentTask)
        {
            if (RandomIdGenerator == null) RandomIdGenerator = new Random();
            Id = RandomIdGenerator.Next(Int32.MaxValue);
            DateCreated = DateTime.Now;

            Init(Name, IdParentTask);
        }

        protected sealed override void Init(string name, int idparenttask)
        {
            Name = name;
            IdParentTask = idparenttask;
            IsPeriodicTask = false;
        }

        protected sealed override void Clear()
        {
            base.Clear();
            foreach (var message in mMessages)
                message.Value.Clear();
        }
        #endregion

        #region Events
        public sealed override bool CheckTimeout(int Timeout)
        {
            try
            {
                if ((DateTime.Now - DateCreated).Seconds > Timeout) return true;
                return false;
            }
            catch (Exception) { }
            return true;
        }

        public sealed override bool CheckComplete()
        {
            try
            {
                foreach (var mess in mMessages)
                    if (!mess.Value.IsComplete) return false;
                return true;
            }
            catch (Exception) { }
            return false;
        }

        public sealed override void TryCloseByComplete()
        {
            if (CheckComplete()) CallTaskComplete();
            if (IsPeriodicTask) Clear();
        }

        public sealed override void TryCloseByTimeout(int Timeout)
        {
            if (CheckTimeout(Timeout)) CallTaskTimeout();
            if (IsPeriodicTask) Clear();
        }
        #endregion

        #region Messages
        public sealed override bool AddMessage<TMessType>(int countMessages = 1, EventTaskMessageAdding<TMessType> Delegate = null, bool AnySender = true)
        {
            try
            {
                if (mMessages.ContainsKey(typeof(TMessType))) return false;

                TaskMessage<TMessType> mess = new TaskMessage<TMessType>(countMessages, AnySender);
                if (Delegate != null) mess.TaskMessageAdding += Delegate;
                mess.Service = Service;
                mMessages.Add(typeof(TMessType), mess);
                return true;
            }
            catch (Exception) { }
            return false;
        }

        public sealed override bool TryMessageComplete(object Message)
        {
            try
            {
                if (!mMessages.ContainsKey(Message.GetType())) return false;
                mMessages[Message.GetType()].CompleteMessage(Message);
                return true;
            }
            catch (Exception) { }
            return false;
        }

        public sealed override TaskMessage<TType> GetMessage<TType>()
        {
            try
            {
                if (mMessages.ContainsKey(typeof(TType))) return (TaskMessage<TType>)mMessages[typeof(TType)];
            }
            catch (Exception) { }
            return null;
        }
        #endregion
    }

}
